﻿using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Runtime.InteropServices;
using OfficeOpenXml;


namespace 垃圾清理
{
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private ObservableCollection<FileItem> _fileItems = new ObservableCollection<FileItem>();
        public ObservableCollection<FileItem> fileItems
        {
            get { return _fileItems; }
            set
            {
                _fileItems = value;
                OnPropertyChanged(nameof(fileItems));
            }
        }

        // 在类的构造函数中设置许可证上下文
        public MainWindow()
        {
            InitializeComponent();
            DataContext = this;

            // 设置EPPlus许可证上下文
            ExcelPackage.License.SetNonCommercialPersonal("aidongsheng");

            // 检查是否以管理员身份运行
            using (var identity = WindowsIdentity.GetCurrent())
            {
                var principal = new WindowsPrincipal(identity);
                if (!principal.IsInRole(WindowsBuiltInRole.Administrator))
                {
                    MessageBox.Show("建议以管理员身份运行此程序，以便能够访问所有系统临时文件夹。", "提示",
                        MessageBoxButton.OK, MessageBoxImage.Information);
                }
            }

            InitializeDrives();
        }


        private void InitializeDrives()
        {
            try
            {
                var drives = DriveInfo.GetDrives()
                    .Where(d => d.IsReady && d.DriveType == DriveType.Fixed)
                    .Select(d => d.Name);

                DriveComboBox.ItemsSource = drives;
                if (drives.Any())
                {
                    DriveComboBox.SelectedIndex = 0;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"初始化磁盘列表失败：{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private async void ScanButton_Click(object sender, RoutedEventArgs e)
        {
            if (DriveComboBox.SelectedItem == null)
            {
                MessageBox.Show("请选择要扫描的磁盘！", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            StatusText.Text = "正在扫描...";
            fileItems.Clear();

            try
            {
                string selectedDrive = DriveComboBox.SelectedItem.ToString();
                await ScanFiles(selectedDrive);
                StatusText.Text = $"扫描完成，找到 {fileItems.Count} 个垃圾文件";
            }
            catch (Exception ex)
            {
                StatusText.Text = "扫描失败";
                MessageBox.Show($"扫描过程中发生错误：{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private async System.Threading.Tasks.Task ScanFiles(string drivePath)
        {
            // 定义垃圾文件类型
            var 垃圾文件扩展名 = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
    {
        // 临时文件
        ".tmp", ".temp",
        // 日志文件
        ".log",
        // 备份文件
        ".bak", ".backup",
        // 缓存文件
        ".cache", ".dmp",
        // 系统更新文件
        ".etl", ".evtx",
        // 其他垃圾文件
        ".old", ".gid", ".chk", ".sik"
    };

            StatusText.Text = "正在扫描垃圾文件...";
            var scannedFiles = new List<string>();

            try
            {
                // 使用自定义的递归方法来安全地遍历目录
                var files = await Task.Run(() =>
                {
                    return GetFilesSafe(drivePath, 垃圾文件扩展名);
                });

                // 处理找到的文件
                foreach (var file in files)
                {
                    try
                    {
                        var fileInfo = new FileInfo(file);

                        // 跳过正在使用的文件
                        if (IsFileLocked(fileInfo))
                            continue;

                        // 跳过系统关键文件
                        if (IsSystemFile(file))
                            continue;

                        await Dispatcher.InvokeAsync(() =>
                        {
                            fileItems.Add(new FileItem
                            {
                                FileName = fileInfo.Name,
                                FilePath = fileInfo.FullName,
                                FileSize = FormatFileSize(fileInfo.Length),
                                IsSelected = false
                            });
                        });

                        scannedFiles.Add(file);
                    }
                    catch (Exception ex)
                    {
                        System.Diagnostics.Debug.WriteLine($"处理文件 {file} 时出错：{ex.Message}");
                    }
                }

                StatusText.Text = $"扫描完成，找到 {scannedFiles.Count} 个垃圾文件";
            }
            catch (Exception ex)
            {
                StatusText.Text = "扫描过程中发生错误";
                MessageBox.Show($"扫描过程中发生错误：{ex.Message}", "错误",
                    MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        // 安全地获取文件的方法
        private List<string> GetFilesSafe(string path, HashSet<string> allowedExtensions)
        {
            var files = new List<string>();
            var directoriesToProcess = new Stack<string>();
            directoriesToProcess.Push(path);

            while (directoriesToProcess.Count > 0)
            {
                var currentDir = directoriesToProcess.Pop();

                try
                {
                    // 跳过系统保护目录
                    if (currentDir.Contains("System Volume Information") ||
                        currentDir.Contains("$RECYCLE.BIN") ||
                        currentDir.Contains("Windows\\WinSxS"))
                        continue;

                    // 添加当前目录中的文件
                    var currentFiles = Directory.GetFiles(currentDir, "*.*")
                        .Where(f => allowedExtensions.Contains(Path.GetExtension(f)));
                    files.AddRange(currentFiles);

                    // 添加子目录到处理队列
                    foreach (var dir in Directory.GetDirectories(currentDir))
                    {
                        directoriesToProcess.Push(dir);
                    }
                }
                catch (UnauthorizedAccessException)
                {
                    // 跳过无权访问的目录
                    continue;
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine($"处理目录 {currentDir} 时出错：{ex.Message}");
                    continue;
                }
            }

            return files;
        }

        // 检查文件是否被占用
        private bool IsFileLocked(FileInfo file)
        {
            try
            {
                using (var stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None))
                {
                    stream.Close();
                }
                return false;
            }
            catch (IOException)
            {
                return true;
            }
        }

        // 检查是否是系统关键文件
        private bool IsSystemFile(string filePath)
        {
            try
            {
                var fileInfo = new FileInfo(filePath);
                return (fileInfo.Attributes & FileAttributes.System) != 0;
            }
            catch
            {
                return true; // 如果无法访问，默认认为是系统文件
            }
        }


        private async System.Threading.Tasks.Task ScanFolder(string folderPath)
        {
            await System.Threading.Tasks.Task.Run(() =>
            {
                try
                {
                    var files = Directory.GetFiles(folderPath, "*", SearchOption.AllDirectories);
                    System.Diagnostics.Debug.WriteLine($"在文件夹 {folderPath} 中找到 {files.Length} 个文件");

                    foreach (var file in files)
                    {
                        Dispatcher.Invoke(() =>
                        {
                            var fileInfo = new FileInfo(file);
                            fileItems.Add(new FileItem
                            {
                                FileName = fileInfo.Name,
                                FilePath = fileInfo.FullName,
                                FileSize = FormatFileSize(fileInfo.Length),
                                IsSelected = false
                            });
                        });
                    }
                }
                catch (UnauthorizedAccessException ex)
                {
                    System.Diagnostics.Debug.WriteLine($"访问文件夹 {folderPath} 被拒绝：{ex.Message}");
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine($"扫描文件夹 {folderPath} 时出错：{ex.Message}");
                }
            });
        }


        private string FormatFileSize(long bytes)
        {
            string[] sizes = { "B", "KB", "MB", "GB", "TB" };
            double len = bytes;
            int order = 0;
            while (len >= 1024 && order < sizes.Length - 1)
            {
                order++;
                len = len / 1024;
            }
            return $"{len:0.##} {sizes[order]}";
        }

        private void SelectAll_Click(object sender, RoutedEventArgs e)
        {
            foreach (var item in fileItems)
            {
                item.IsSelected = true;
            }
            UpdateSelectedSize();
        }

        private void InverseSelection_Click(object sender, RoutedEventArgs e)
        {
            foreach (var item in fileItems)
            {
                item.IsSelected = !item.IsSelected;
            }
            UpdateSelectedSize();
        }

        private void CleanButton_Click(object sender, RoutedEventArgs e)
        {
            var selectedFiles = fileItems.Where(f => f.IsSelected).ToList();

            if (!selectedFiles.Any())
            {
                MessageBox.Show("请选择要清理的文件！", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            if (MessageBox.Show($"确定要删除选中的 {selectedFiles.Count} 个文件吗？", "确认删除",
    MessageBoxButton.YesNo, MessageBoxImage.Warning) != MessageBoxResult.Yes)
            {
                return;
            }

            try
            {
                int deletedCount = 0;
                foreach (var file in selectedFiles.ToList())
                {
                    try
                    {
                        File.Delete(file.FilePath);
                        fileItems.Remove(file);
                        deletedCount++;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show($"删除文件 {file.FileName} 失败：{ex.Message}", "错误",
                            MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }

                StatusText.Text = $"成功删除 {deletedCount} 个文件";
                UpdateSelectedSize();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"清理过程中发生错误：{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void ExportButton_Click(object sender, RoutedEventArgs e)
        {
            var selectedFiles = fileItems.Where(f => f.IsSelected).ToList();

            if (!selectedFiles.Any())
            {
                MessageBox.Show("请选择要导出的文件记录！", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                return;
            }

            SaveFileDialog saveFileDialog = new SaveFileDialog
            {
                Filter = "Excel文件|*.xlsx|所有文件|*.*",
                FileName = $"垃圾文件记录_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx"
            };

            if (saveFileDialog.ShowDialog() == true)
            {
                try
                {
                    // 设置EPPlus的许可证上下文
                    //ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;

                    using (var package = new ExcelPackage())
                    {
                        var worksheet = package.Workbook.Worksheets.Add("垃圾文件记录");

                        // 设置表头
                        worksheet.Cells[1, 1].Value = "垃圾文件清理记录";
                        worksheet.Cells[1, 1].Style.Font.Bold = true;
                        worksheet.Cells[1, 1].Style.Font.Size = 14;
                        worksheet.Cells["A1:D1"].Merge = true;

                        worksheet.Cells[2, 1].Value = $"导出时间：{DateTime.Now:yyyy-MM-dd HH:mm:ss}";
                        worksheet.Cells["A2:D2"].Merge = true;

                        // 设置列标题
                        var headers = new string[] { "文件名", "文件路径", "文件大小", "创建时间" };
                        for (int i = 0; i < headers.Length; i++)
                        {
                            worksheet.Cells[4, i + 1].Value = headers[i];
                        }

                        // 设置列标题样式
                        using (var range = worksheet.Cells[4, 1, 4, 4])
                        {
                            range.Style.Font.Bold = true;
                            range.Style.Fill.PatternType = OfficeOpenXml.Style.ExcelFillStyle.Solid;
                            range.Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.LightGray);
                        }

                        // 填充数据
                        int row = 5;
                        foreach (var file in selectedFiles)
                        {
                            worksheet.Cells[row, 1].Value = file.FileName;
                            worksheet.Cells[row, 2].Value = file.FilePath;
                            worksheet.Cells[row, 3].Value = file.FileSize;

                            try
                            {
                                var fileInfo = new FileInfo(file.FilePath);
                                worksheet.Cells[row, 4].Value = fileInfo.CreationTime.ToString("yyyy-MM-dd HH:mm:ss");
                            }
                            catch
                            {
                                worksheet.Cells[row, 4].Value = "无法获取";
                            }

                            row++;
                        }

                        // 添加统计信息
                        worksheet.Cells[row + 1, 1].Value = "总计";
                        worksheet.Cells[row + 1, 1].Style.Font.Bold = true;
                        worksheet.Cells[row + 1, 3].Value = $"{selectedFiles.Count} 个文件";
                        worksheet.Cells[row + 1, 3].Style.Font.Bold = true;

                        // 自动调整列宽
                        worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns();

                        // 保存文件
                        package.SaveAs(new FileInfo(saveFileDialog.FileName));
                        MessageBox.Show("导出成功！", "提示", MessageBoxButton.OK, MessageBoxImage.Information);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"导出失败：{ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }



        private void UpdateSelectedSize()
        {
            long totalSize = 0;
            foreach (var item in fileItems.Where(f => f.IsSelected))
            {
                try
                {
                    totalSize += new FileInfo(item.FilePath).Length;
                }
                catch
                {
                    // 忽略无法访问的文件
                }
            }
            SelectedSizeText.Text = $"已选择: {FormatFileSize(totalSize)}";
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public class FileItem : INotifyPropertyChanged
    {
        private bool _isSelected;
        private string _fileName;
        private string _filePath;
        private string _fileSize;

        public bool IsSelected
        {
            get { return _isSelected; }
            set
            {
                _isSelected = value;
                OnPropertyChanged(nameof(IsSelected));
            }
        }

        public string FileName
        {
            get { return _fileName; }
            set
            {
                _fileName = value;
                OnPropertyChanged(nameof(FileName));
            }
        }

        public string FilePath
        {
            get { return _filePath; }
            set
            {
                _filePath = value;
                OnPropertyChanged(nameof(FilePath));
            }
        }

        public string FileSize
        {
            get { return _fileSize; }
            set
            {
                _fileSize = value;
                OnPropertyChanged(nameof(FileSize));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
